#include "Pf.h"

#ifdef PF_PLATFORM_PC

#include "PfPlatform.PC.h"

namespace pf
{
	PlatformHandle CreatePlatform()
	{
		return new PlatformPC;
	}

	void PlatformPC::Initialise(InitParamsHandle hInitParams)
	{
		m_quitRequested = false;
		m_hWnd = 0;

		SelectDisplayConfig(hInitParams->m_hDisplayConfigSelector);

		CreateDisplay(hInitParams);

		m_keyboard.Initialise();
	}

	void PlatformPC::Shutdown()
	{
	}

	bool PlatformPC::Present()
	{
		bool quitMessage = false;
		m_keyboard.Step();

		// Main message loop
		if (!m_quitRequested)
		{
			MSG msg = {0};

			while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
				quitMessage = (msg.message == WM_QUIT);
			}
		}

		return !m_quitRequested && !quitMessage;
	}

	LRESULT CALLBACK PlatformPC::StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
		PlatformPCHandle hPlatformPC = GetPlatform();
  		return hPlatformPC->WndProc(hWnd, message, wParam, lParam);
	}

	void PlatformPC::CreateDisplay(InitParamsHandle hInitParams)
	{
		HINSTANCE hInstance = GetModuleHandle(NULL);

		// Register class
		WNDCLASSEX wcex;
		wcex.cbSize = sizeof( WNDCLASSEX );
		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = StaticWndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = NULL;
		wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
		wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
		wcex.lpszMenuName = NULL;
		wcex.lpszClassName = "somethingclass";
		wcex.hIconSm = NULL;
		if( RegisterClassEx( &wcex ) )
		{
			// Create window
			RECT rc = { 0, 0, (LONG)m_pSelectedDisplayConfig->m_width, (LONG)m_pSelectedDisplayConfig->m_height};
			AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
			m_hWnd = CreateWindow( "somethingclass", hInitParams->m_szTitle, WS_OVERLAPPEDWINDOW,
				CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
				NULL );

			ShowWindow(m_hWnd, hInitParams->m_startVisible ? 1 : 0);
		}
	}

	void PlatformPC::SelectDisplayConfig(IDisplayConfigSelectorHandle hDisplayConfigSelector)
	{
		if (hDisplayConfigSelector.IsValid())
		{
			m_displayConfig.m_width = 1920;
			m_displayConfig.m_height = 1080;
			m_pSelectedDisplayConfig = hDisplayConfigSelector->ConfigureDisplay(&m_displayConfig, 1);
		}
		else
		{
			// Application doesn't care about display config, so just select a default
			m_displayConfig.m_width = 640;
			m_displayConfig.m_height = 480;
			m_pSelectedDisplayConfig = &m_displayConfig;
		}
	}

	LRESULT PlatformPC::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
		PAINTSTRUCT ps;
		HDC hdc;

		switch( message )
		{
		case WM_PAINT:
			hdc = BeginPaint( hWnd, &ps );
			EndPaint( hWnd, &ps );
			break;

		case WM_DESTROY:
			m_quitRequested = true;
			break;

		case WM_KEYUP:
			
			m_keyboard.SetKeyUp(wParam);
			break;

		case WM_KEYDOWN:
			m_keyboard.SetKeyDown(wParam);
			break;

		case WM_SYSKEYDOWN:
			break;

		case WM_SYSKEYUP:
			break;

		default:
			return DefWindowProc( hWnd, message, wParam, lParam );
		}

		return 0;
	}

	InputKeyboardHandle PlatformPC::GetKeyboard()
	{
		return m_keyboard;
	}
}

#endif // PF_PLATFORM_PC